home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / snip0493.zip / FSCANBIN.C < prev    next >
C/C++ Source or Header  |  1993-04-05  |  4KB  |  116 lines

  1. /* fscanbin.c -- scan binary fields via format string
  2. **
  3. **  public domain by Ray Gardner   Englewood, Colorado   11/29/89
  4. **
  5. **  Usage: fscanbin(FILE *fp, char *format, ...)
  6. **
  7. **  where format string contains specifiers:
  8. **   -ddd  means skip ddd bytes
  9. **   i     means read a 16-bit int
  10. **   l     means read a 32-bit int
  11. **   sddd  means read a character string of up to ddd bytes
  12. **           reads up to a nul byte if ddd is zero or missing
  13. **   cnnn  means read a character field of nnn bytes (not nul-terminated)
  14. **           reads one byte if nnn is zero or missing
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <stdarg.h>
  20. #include <ctype.h>
  21.  
  22. typedef unsigned short int16;
  23. typedef unsigned long int32;
  24.  
  25. #define int16swap(n)  (*n = (*n << 8) | (*n >> 8))
  26.  
  27. #define int32swap(n)  (\
  28.                         int16swap(&((int16 *)n)[0]),\
  29.                         int16swap(&((int16 *)n)[1]),\
  30.                         *n = (*n << 16) | (*n >> 16)\
  31.                         )
  32.  
  33. #define maxk 32767
  34.  
  35. int fscanbin (FILE *fp, char *format, ...)
  36. {
  37.       va_list argp;
  38.       unsigned char *p;
  39.       unsigned k;
  40.       int c;
  41.       char *charp;
  42.       int16 *int16p;
  43.       int32 *int32p;
  44.       int bytes_read;
  45.  
  46.       bytes_read = 0;
  47.       va_start(argp, format);
  48.       for ( p = (unsigned char *)format; *p; )
  49.       {
  50.             switch( *p & 0xFF )
  51.             {
  52.             case '-':
  53.                   for ( k = 0, c = *++p; isdigit(c); c = *++p )
  54.                         k = 10 * k + c - '0';
  55.                   if ( k == 0 )
  56.                         k = 1;
  57.                   if ( fseek(fp, (long)k, SEEK_CUR) )
  58.                         return -2;     /* i/o error */
  59.                   bytes_read += k;
  60.                   break;
  61.  
  62.             case 'i':
  63.                   int16p = va_arg(argp, int16 *);
  64.                   if ( fread((void *)int16p, sizeof(int16), 1, fp) != 1 )
  65.                         return -2;     /* i/o error */
  66. #if SWAP16
  67.                   int16swap(int16p);
  68. #endif
  69.                   p++;
  70.                   bytes_read += sizeof(int16);
  71.                   break;
  72.  
  73.             case 'l':
  74.                   int32p = va_arg(argp, int32 *);
  75.                   if ( fread((void *)int32p, sizeof(int32), 1, fp) != 1 )
  76.                         return -2;     /* i/o error */
  77. #if SWAP32
  78.                   int32swap(int32p);
  79. #endif
  80.                   p++;
  81.                   bytes_read += sizeof(int32);
  82.                   break;
  83.  
  84.             case 's':
  85.                   charp = va_arg(argp, char *);
  86.                   for ( k = 0, c = *++p; isdigit(c); c = *++p )
  87.                         k = 10 * k + c - '0';
  88.                   do
  89.                   {
  90.                         c = getc(fp);
  91.                         if ( c == EOF )
  92.                               return -2;
  93.                         *charp++ = (char)c;
  94.                         bytes_read++;
  95.                   } while ( c && (k == 0 || --k) );
  96.                   break;
  97.  
  98.             case 'c':
  99.                   charp = va_arg(argp, char *);
  100.                   for ( k = 0, c = *++p; isdigit(c); c = *++p )
  101.                         k = 10 * k + c - '0';
  102.                   if ( k == 0 )
  103.                         k = 1;
  104.                   if ( fread((void *)charp, sizeof(char), k, fp) != k )
  105.                         return -2;     /* i/o error */
  106.                   bytes_read += k;
  107.                   break;
  108.  
  109.             default:
  110.                   return -1; /* bad format */
  111.             }
  112.       }
  113.       va_end(argp);
  114.       return bytes_read;
  115. }
  116.